查看原文
其他

这个字典库引起了 Python 之父的注意!你用过吗?

Linux爱好者 2024-03-09

The following article is from Python开发者 Author 南风草木香

【导语】:本文介绍了Bi-Dictionary 库,即“Bi-directional Dictionary”双向字典,顾名思义,该库基于Python中的字典增加了由“值”访问键的功能,开发者可以通过值来反向查找键,使得处理字典更加方便。同时,该库也引起了 Python 之父 Guido 的注意,因此,很有必须学习Bi-Dictionary 库。

简介

字典是Python中最常见的数据结构之一,在日常开发中使用的频率很高。字典由一些键值对构成,我们只能通过键访问值,但是无法通过值访问键。目前有一个第三方库很好的解决了这个问题 - Bi-Dictionary,通过使用它,我们可以由值访问键。该库甚至引起了 Python 之父 Guido 的注意,因此这一特性未来可能会被加入到Python语法中。

安装

我们可以使用pip安装bidict库:

pip install bidict

随后,需要导入该库才能使用:

from bidict import bidict

简单使用

  1. 初步使用

我们首先通过创建一个字典,该字典的键为国家的简称,值为国家的全名,再用bidict初始化这个字典:

country_abbr_bidict = bidict({'USA': 'The United States of America'})

这样,我们只需要使用inverse()方法,就可以通过国家全称获取国家简称了:

from bidict import bidict
country_abbr_bidict = bidict({'USA''The United States of America'})
shortName = country_abbr_bidict.inverse['The United States of America']
print(shortName)

结果为:USA

我们可以对比下原字典和反转后的区别:

from bidict import bidict
country_abbr_bidict = bidict({'USA''The United States of America'})
print(country_abbr_bidict)
print(country_abbr_bidict.inverse)

结果显示,inverse()方法反转了原字典的键值位置:

bidict({'USA''The United States of America'})
bidict({'The United States of America''USA'})
  1. 为何不使用Python的字典呢?

我们也可以在字典中把键值互换,再存储一份数据,这样也能实现与bidict相同的效果。我们来尝试一下:

country_abbr_dict = {
    'USA''The United States of America',
    'The United States of America''USA'
}

如果我们想把USA更新成US,可以使用update()方法,像下面这样:

country_abbr_dict.update({
    'US''The United States of America',
    'The United States of America''US'
})

这似乎看起来很完美,但是字典仍然保留了原来的数据:

from bidict import bidict
country_abbr_dict = {
    'USA''The United States of America',
    'The United States of America''USA'
}
country_abbr_dict.update({
    'US''The United States of America',
    'The United States of America''US'
})
print(country_abbr_dict)

在结果中我们可以看到USA也在字典中:

{'USA': 'The United States of America', 'The United States of America': 'US', 'US': 'The United States of America'}

为了避免这个问题,只能定义一个函数:

def update(d, key, val):
    oldval = d.pop(key, object())
    d.pop(oldval, None)
    oldkey = d.pop(val, object())
    d.pop(oldkey, None)
    d.update({key: val, val: key})

country_abbr_dict = {
    'USA''The United States of America',
    'The United States of America''USA'
}
update(country_abbr_dict, 'US''The United States of America')
print(country_abbr_dict)

这样就可以成功更新字典了:

{'US': 'The United States of America', 'The United States of America': 'US'}

如果使用Bidict,就非常简单了:

country_abbr_bidict.inverse['The United States of America'] = 'US'
print(country_abbr_bidict)

bidict({'US': 'The United States of America'})

Bidict用起来,明显更方便!

  1. Bidict的其他用途
  • 在查找值之前,传入默认值

Bidict继承了Python字典中的大部分特性。例如,当我们想要通过键访问bidict中的某个值时,可以传入一个默认值。这样,如果bidict中没有该值,就会将默认值作为结果返回。

from bidict import bidict
country_abbr_bidict = bidict({
    'US''The United States of America',
})
print(country_abbr_bidict.get('AU''Australia'))

结果就是我们传入的默认值:Australia

  • 加入新的键值对

Bidict加入新键值对的方式与Python的原生字典一样,我们来试试:

from bidict import bidict
country_abbr_bidict = bidict({
    'US''The United States of America',
})
country_abbr_bidict['AU'] = 'Australia'
country_abbr_bidict['CA'] = 'Canada'
print(country_abbr_bidict)

结果为:

bidict({'US': 'The United States of America', 'AU': 'Australia', 'CA': 'Canada'})

  • 检验Bidict中是否有某个特定值

(1)我们可以使用in关键字来检查Bidict中是否有CA:

'CA' in country_abbr_bidict

我们可以得到一个布尔值,表示该键是否存在于Bidict中:True

(2)同样我们也可以检查Bidict中是否有某个值,

'Australia' in country_abbr_bidict.inverse

结果显示Bidict中有该值:True

  • Pop and Delete方法

除了上述特性外,我们还可以使用Pop and Delete方法。

(1)pop()方法可以从Bidict中弹出键值对

country_abbr_bidict.pop('AU')

会返回该键对应的值:Australia

我们再看看Bidict:country_abbr_bidict

发现里面没有AU这个键值对了:bidict({'US': 'The United States of America', 'CA': 'Canada'})

(2)delete()方法可以通过键或者值的方式删除键值对

del country_abbr_bidict.inverse['Canada']
print(country_abbr_bidict)

结果显示删除成功:bidict({'US': 'The United States of America'})

  1. 约束

Python的设计理念是当程序出现错误时,一定要显示出来,Bidict的设计也遵循了这一点。Bidict的一个约束是键、值都要唯一,这是因为值也有可能会被当作键使用。因此,当我们想在Bidict中加入一个新的键值对(该键值对的值已经被其他键使用),就会报错。例如,我们想把US - The United States of America加入Bidict中,但是原字典中已有USA - The United States of America了:

from bidict import bidict
country_abbr_bidict = bidict({
    'USA''The United States of America',
})
country_abbr_bidict['US'] = 'The United States of America'

会产生如下错误:

Traceback (most recent call last):
  File "F:/Documents/其他资料/pythonprojects/01practice/app.py", line 5, in <module>
    country_abbr_bidict['US'] = 'The United States of America'
  File "F:\python\lib\site-packages\bidict\_bidict.py", line 67, in __setitem__
    self.put(key, val, on_dup=self.on_dup)
  File "F:\python\lib\site-packages\bidict\_bidict.py", line 93, in put
    self._update([(key, val)], on_dup=on_dup)
  File "F:\python\lib\site-packages\bidict\_base.py", line 455, in _update
    dedup_result = self._dedup(key, val, on_dup)
  File "F:\python\lib\site-packages\bidict\_base.py", line 350, in _dedup
    raise ValueDuplicationError(val)
bidict.ValueDuplicationError: The United States of America

我们可以使用forceput()方法来避免这一错误:country_abbr_bidict.forceput('USA', 'The United States of America')

但是,如果出现了两个键的值相同这种情况,该方法会把原来的键覆盖:bidict({'US': 'The United States of America'})

  1. 其他特性
  • 更新多个键值对

putall()方法可以同时加入多个键值对到Bidict中,但传入的参数必须是可迭代的。

country_abbr_bidict.putall([
    ('AU''Australia'),
    ('CA''Canada')
])
print(country_abbr_bidict)

结果显示加入成功:bidict({'USA': 'The United States of America', 'AU': 'Australia', 'CA': 'Canada'})

当某个键值对无法传入时,那么其他键值对也无法传入:

country_abbr_bidict = bidict({'US''United States of America'})
country_abbr_bidict.putall([
    ('AU''Australia'),
    ('CA''Canada'),
    ('US''The United States of America')
])

这里出现了报错:

Traceback (most recent call last):
  File "F:/Documents/其他资料/pythonprojects/01practice/app.py", line 3, in <module>
    country_abbr_bidict.putall([
  File "F:\python\lib\site-packages\bidict\_bidict.py", line 179, in putall
    self._update(items, on_dup=on_dup)
  File "F:\python\lib\site-packages\bidict\_base.py", line 443, in _update
    target._update(arg, kw, rbof=False, on_dup=on_dup)
  File "F:\python\lib\site-packages\bidict\_base.py", line 455, in _update
    dedup_result = self._dedup(key, val, on_dup)
  File "F:\python\lib\site-packages\bidict\_base.py", line 343, in _dedup
    raise KeyDuplicationError(key)
bidict.KeyDuplicationError: US

而其他键值对也没有传入到Bidict中:bidict({'US': 'United States of America'})

  • forceupdate()方法的优先级

如果我们想使用该方法传入多个键值对,对Bidict进行更新,那么就要注意传入数据的先后顺序了。

如果把USA放到最后,那么最终Bidict就会使用该键:

country_abbr_bidict = bidict({'US''United States of America'})
country_abbr_bidict.forceupdate([
    ('US''The United States of America'),
    ('USA''The United States of America')
])

结果为:bidict({'USA': 'The United States of America'})

如果把US放到最后,那么字典就会将US作为键。

country_abbr_bidict.forceupdate([
    ('USA''The United States of America'),
    ('US''The United States of America')
])
print(country_abbr_bidict)

结果为:bidict({'US': 'The United States of America'})

  • 与其他数据结构交互

Bidict可以转换为其他数据结构,反之亦然。例如,我们可以把Bidict转换为字典:dict(country_abbr_bidict)

结果为:{'US': 'United States of America'}

我们再把字典转换为Bidict: bidict(dict(country_abbr_bidict))

结果为:bidict({'US': 'United States of America'})

结论

在本文中,我介绍了Bi-Dictionary库-双向字典,也称为Bidict。它不仅改进了Python字典的缺点,而且遵循了Python的设计原则。非常值得学习!

参考原文:
https://towardsdatascience.com/python-bi-dictionary-key-can-be-value-and-value-can-be-key-50715a2046af

- EOF -

推荐阅读  点击标题可跳转

1、实用!f-strings 比你想象的还要强大

2、很期待!尝鲜 Python 3.11 的 5 个新特性

3、Python 处理超大 JSON 文件,这个方法简单!


↓推荐关注↓

「Python开发精选」分享 Python 技术文章、资源、课程、资讯。


点赞和在看就是最大的支持❤️

继续滑动看下一个

这个字典库引起了 Python 之父的注意!你用过吗?

向上滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存